package com.md.util;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.md.base.exception.ServerException;
import com.md.value.constants.Constants;
import com.md.value.enums.ErrorEnum;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 2021-10-09 11:27
 *
 * @author 刘骄阳
 */
@Slf4j
@UtilityClass
public final class HttpUtil {
  /**
   * 获取ip地址
   *
   * @param request request
   * @return ip地址
   */
  public static String getIpAddress(final HttpServletRequest request) {
    log.info("请求方式: {}, 请求地址: {}, 获取请求端口: {}, 地址拼接内容: {}, 请求客户端的IP: {}, 接收当前请求的IP: {}, " +
        "接收当前请求的主机名: {}, 接收当前请求的端口号: {}, 请求客户端的完整主机名: {}", request.getMethod(),
      request.getRequestURI(), request.getRemotePort(), request.getQueryString(), request.getRemoteAddr(),
      request.getLocalAddr(), request.getLocalName(), request.getLocalPort(), request.getRemoteHost());
    String ip = null;
    String[] temp = Constants.ADDRESS_NAME;
    for (String head : temp) {
      ip = request.getHeader(head);
      if (ObjectUtil.notEmpty(ip) && !Constants.UNKNOWN.equalsIgnoreCase(ip)) {
        //说明获取到ip地址了
        break;
      }
    }
    if (ip == null) {
      ip = request.getRemoteAddr();
    }
    if ("0:0:0:0:0:0:0:1".equalsIgnoreCase(ip)) {
      return Constants.LOCAL_IP;
    } else {
      return ip;
    }
  }

  public static HttpServletResponse getHttpServletResponse() {
    ServletRequestAttributes servletRequestAttributes =
      (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    if (servletRequestAttributes == null) {
      return null;
    }
    return servletRequestAttributes.getResponse();
  }

  public static HttpServletRequest getHttpServletRequest() {
    ServletRequestAttributes servletRequestAttributes =
      (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    if (servletRequestAttributes == null) {
      return null;
    }
    return servletRequestAttributes.getRequest();
  }

  public static String buildServiceUrl(final NacosServiceManager nacosServiceManager,
                                       final NacosDiscoveryProperties properties,
                                       final String serverName) {
    try {
      Instance instance = nacosServiceManager.getNamingService(properties.getNacosProperties())
        .getAllInstances(serverName).stream().filter(Instance::isEnabled).filter(Instance::isHealthy)
        .findFirst().orElse(null);
      if (ObjectUtil.isEmpty(instance)) {
        throw ServerException.build(ErrorEnum.SYSTEM_ERROR.getCode(), "No " + serverName + " instance found!");
      }
      return "http://" + instance.getIp() + ":" + instance.getPort();
    } catch (NacosException e) {
      log.error("Get instance failed, cause by: {}", e.getMessage(), e);
      throw ServerException.build(ErrorEnum.SYSTEM_ERROR.getCode(), e.getMessage());
    }
  }

  public static String buildServiceUrl(final String serverName) {
    return SystemUtils.retryFunction(() -> buildServiceUrl(SpringContextUtil.getBean(NacosServiceManager.class),
      SpringContextUtil.getBean(NacosDiscoveryProperties.class), serverName));
  }
}
